package com.bluegalaxy.nhb.snservice.support.cron;

import com.bluegalaxy.nhb.snservice.support.util.SysOutUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.concurrent.*;

/**
 * @Auther: nanhb
 * @Date: 2020/8/7 16:17
 * @Description:
 */
public abstract class SNCron implements CronCallable {
    private final ExecutorService exec = Executors.newFixedThreadPool(1);
    private String cronName;
    private long timeout = 600000L;
    private File lockFile;
    private FileOutputStream fos;
    private FileChannel fc;
    private FileLock fl;
    private boolean isExit;

    private SNCron() {
    }

    public SNCron(String cronName, long timeout, boolean isExit) {
        this.cronName = cronName;
        this.timeout = timeout;
        this.isExit = isExit;
    }

    private void init() throws Exception {
        if (this.cronName != null) {
            this.lockFile = new File(System.getProperty("user.dir") + File.separator + this.cronName + ".lock");
            this.fos = new FileOutputStream(this.lockFile);
            this.fc = this.fos.getChannel();
        } else {
            throw new Exception("cronName不能为空，请设置cronName");
        }
    }

    private void unlock() {
        if (this.fl != null) {
            try {
                this.fl.release();
            } catch (IOException var17) {
                var17.printStackTrace();
            } finally {
                this.fl = null;
            }
        }

        if (this.fc != null) {
            try {
                this.fc.close();
            } catch (IOException var15) {
                var15.printStackTrace();
            } finally {
                this.fc = null;
            }
        }

        if (this.fos != null) {
            try {
                this.fos.close();
            } catch (IOException var14) {
                var14.printStackTrace();
            }
        }

    }

    private boolean validateLock() throws IOException {
        if (this.fc != null) {
            this.fl = this.fc.tryLock();
            return this.fl != null;
        } else {
            return true;
        }
    }

    public void start() throws Exception {
        SysOutUtil.out("定时任务【" + this.cronName + "】任务执行开始");
        this.init();
        if (this.validateLock()) {
            try {
                Future<Boolean> future = this.exec.submit(this);
                boolean b = (Boolean)future.get(this.timeout, TimeUnit.MILLISECONDS);
                SysOutUtil.out("定时任务【" + this.cronName + "】成功返回:" + b);
            } catch (TimeoutException var7) {
                SysOutUtil.out("定时任务【" + this.cronName + "】处理超时啦....");
                var7.printStackTrace();
            } catch (Exception var8) {
                SysOutUtil.out("定时任务【" + this.cronName + "】处理失败.");
                var8.printStackTrace();
            } finally {
                this.exec.shutdown();
                this.unlock();
                if (this.isExit) {
                    System.exit(0);
                }

            }
        } else {
            SysOutUtil.out("定时任务【" + this.cronName + "】正在执行。不能重复执行");
            if (this.isExit) {
                System.exit(0);
            }
        }

    }

    public Boolean call() throws Exception {
        this.cronThreadRun();
        return true;
    }
}
